import { urlEncodeValue } from "../helper.ts";
import { FieldParam, FieldTupleParam } from "../main.ts";
import { Handler } from "./index.ts";

export class BtHandler implements Handler {
  check<T, Extra>(param: FieldParam<T, Extra>): void {
    if (!(param.value instanceof Array) || param.value.length !== 2) {
      throw new Error(`${String(param.op)} must has two values`);
    }
  }

  process<T, Extra>(param: FieldParam<T, Extra>, group?: string): string {
    if (!(param.value instanceof Array)) return "";
    if (group) {
      return `${group}.${String(param.label)}-op=${param.op}` +
        "&" +
        `${group}.${String(param.label)}-0=${urlEncodeValue(param.value[0])}` +
        "&" +
        `${group}.${String(param.label)}-1=${urlEncodeValue(param.value[1])}`;
    }

    return `${String(param.label)}-op=${param.op}` +
      "&" +
      `${String(param.label)}-0=${urlEncodeValue(param.value[0])}` +
      "&" +
      `${String(param.label)}-1=${urlEncodeValue(param.value[1])}`;
  }

  processTuple<T, Extra>(
    param: FieldTupleParam<T, Extra>,
    group?: string,
  ): string {
    if (!(param[2] instanceof Array)) return "";
    if (group) {
      return `${group}.${String(param[0])}-op=${param[1]}` +
        "&" +
        `${group}.${String(param[0])}-0=${urlEncodeValue(param[2][0])}` +
        "&" +
        `${group}.${String(param[0])}-1=${urlEncodeValue(param[2][1])}`;
    }

    return `${String(param[0])}-op=${param[1]}` +
      "&" +
      `${String(param[0])}-0=${urlEncodeValue(param[2][0])}` +
      "&" +
      `${String(param[0])}-1=${urlEncodeValue(param[2][1])}`;
  }

  checkTuple<T, Extra>(param: FieldTupleParam<T, Extra>): void {
    if (!(param[2] instanceof Array) || param[2].length !== 2) {
      throw new Error(`${String(param[1])} must has two values`);
    }
  }

  processObj<T, Extra>(
    obj: object,
    param: FieldParam<T, Extra>,
    group?: string,
  ): void {
    if (!(param.value instanceof Array)) return;
    if (group) {
      Object.assign(obj, {
        [`${group}.${param.label}-op`]: param.op,
        [`${group}.${param.label}-0`]: urlEncodeValue(param.value[0]),
        [`${group}.${param.label}-1`]: urlEncodeValue(param.value[1]),
      });
    } else {
      Object.assign(obj, {
        [`${param.label}-op`]: param.op,
        [`${param.label}-0`]: urlEncodeValue(param.value[0]),
        [`${param.label}-1`]: urlEncodeValue(param.value[1]),
      });
    }
  }

  processObjTuple<T, Extra>(
    obj: object,
    param: FieldTupleParam<T, Extra>,
    group?: string,
  ): void {
    if (!(param[2] instanceof Array)) return;
    if (group) {
      Object.assign(obj, {
        [`${group}.${param[0]}-op`]: param[1],
        [`${group}.${param[0]}-0`]: urlEncodeValue(param[2][0]),
        [`${group}.${param[0]}-1`]: urlEncodeValue(param[2][1]),
      });
    } else {
      Object.assign(obj, {
        [`${param[0]}-op`]: param[1],
        [`${param[0]}-0`]: urlEncodeValue(param[2][0]),
        [`${param[0]}-1`]: urlEncodeValue(param[2][1]),
      });
    }
  }
}
